<template>
  <div>
    <template v-if="multiple">
      <span class="dol-upload-block" v-for="(file,index) in value" :style="imageStyle" >
        <yd-lightbox class="dol-upload-img-panel">
          <yd-lightbox-img :src="$Dolphin.path.publicPath + (valueType==='data'?file['filePath']:file)" class="img-responsive"></yd-lightbox-img>
        </yd-lightbox>

        <span class="dol-upload-remove" v-if="!loading[index]" @click="remove(file, index)"><mu-icon value="clear" /></span>
      </span></template><template v-else-if="value">
      <span class="dol-upload-block" :style="imageStyle" >
        <yd-lightbox class="dol-upload-img-panel">
          <yd-lightbox-img :src="$Dolphin.path.publicPath + (valueType==='data'?value['filePath']:value)" class="img-responsive"></yd-lightbox-img>
        </yd-lightbox>

        <span class="dol-upload-remove" @click="remove(value)"><mu-icon value="clear" /></span>
      </span>
    </template><span class="dol-upload-block dol-upload-add">
      <mu-icon value="add"></mu-icon>
      <input type="file" :accept="accept" @change="selectFile" :multiple="multiple" />
    </span>
  </div>
</template>

<script>
  //TODO 预加载 + 上传过程提示未实现
  //TODO 单图上传，应该可配置点击图片是替换图片还是预览
  export default {
    props: {
      server: {type: String, default: '/system/tool/file/base64'},        //base64数据上传地址
      serverRemove: {type: String, default: '/system/tool/file/remove/{id}'},   //文件删除地址
      accept: {type: String, default: 'image/*'},                         //input file选择类型
      multiple: {type: Boolean, default: false},                           //是否支持多文件选择
      append: {type: Boolean, default: true},                            //是否支持追加文件

      compress: {type: Boolean, default: true},                           //是否压缩
      compressType: {type: String, default: 'width'},                     //压缩方式，fileSize | percent | width
      compressFileSize: {type: Number, default: 100},                     //压缩文件大小，当compressType == fileSize时使用，单位是K
      compressPercent: {type: Number, default: 0.5},                      //压缩比例，当compressType == percent时使用
      compressWidth: {type: Number, default: 420},                        //压缩按图片实际宽度，当compressType == width时使用，单位是px

      imageStyle: {type: Object},                                         //预览图片样式

      value:{},                                                           //绑定数据
      valueType:{type: String, default: 'data'},                          //数据类型 data | path
    },
    data() {
      return {
        files: [],
        loading: {},
        data: [],

        uploading: false,
      }
    },
    computed: {
      imgKey() {
        return this.compress ? 'compressData' : 'base64';
      },
    },
    methods: {
      /**
       * 选中文件后，上传上件并绑定数据
       * @param $event
       */
      selectFile($event) {
        let files = $event.target.files;

        let promise = [], i;
        for (i = 0; i < files.length; i++) {
          promise.push(this.process(files[i]));
        }

        Promise.all(promise).then(allData => {
          let value;
          if(this.multiple){ //多文件上传时
            if(this.append){ //判断是否支持追加
              value = this.value;
            }else{
              //TODO 删除后台数据和文件
              value = [];
            }
            if(this.valueType === 'data'){
              value = value.concat(allData);
            }else{
              allData.forEach(d => {
                value.push(d.filePath);
              });
            }
          }else{  //单文件上传
            value = allData[0];
          }
          this.$emit('upload', allData, value);
          this.$emit('input', value);
        });
      },

      /**
       * 处理单个文件，1.转base64；2.压缩；3.上传
       * @param file
       * @return {Promise} fileData
       */
      process(file) {
        return this.base64(file).then(() => {
          if(this.compress){
            return this.compressFile(file);
          }else{
            return Promise.resolve();
          }
        }).then(() => {
          return this.uploadBase64(file);
        }).then(reData => {
          return Promise.resolve(reData.data);
        });
      },

      /**
       * 单文件转base64
       * @param file
       * @return {Promise}
       */
      base64(file) {
        return new Promise((resolve, reject) => {
          let reader = new FileReader();
          // 转成base64
          reader.onload = () => {
            file.base64 = reader.result;
            resolve();
          };
          reader.readAsDataURL(file);    //转成Base64格式
        });
      },

      /**
       * 根据配置压缩图片，分为按文件大小压缩、按比例压缩、按图片宽度压缩3种
       * @param file
       * @return {Promise<any>}
       */
      compressFile(file) {
        return new Promise((resolve, reject) => {
          let image = document.createElement('img');
          image.onload = () => {
            let percent = this.getCompressPercent(file, image.width);
            let canvas = document.createElement('canvas');
            let context = canvas.getContext('2d');
            let imageWidth = image.width * percent,    //压缩图片的大小
              imageHeight = image.height * percent,
              offsetX = 0,
              offsetY = 0;
            canvas.width = imageWidth;
            canvas.height = imageHeight;
            context.fillStyle = "white";
            context.fillRect(0, 0, imageWidth, imageHeight);

            context.drawImage(image, offsetX, offsetY, imageWidth, imageHeight);
            file.compressData = canvas.toDataURL('image/jpeg', percent);
            resolve();
          };
          image.setAttribute('src', file.base64);
        });
      },
      getCompressPercent(file, width){
        let percent = 1;
        switch (this.compressType) {
          case 'percent':
            percent = this.compressPercent;
            break;
          case 'fileSize':
            percent = Math.min(1, this.compressFileSize * 1024 / file.size);
            break;
          case 'width':
            percent = Math.min(1, this.compressWidth / width);
        }

        return percent;
      },

      /**
       * 上传base64的图片文件
       * @param file
       */
      uploadBase64(file) {
        let uploadData = file[this.imgKey];
        uploadData = uploadData.substr(uploadData.indexOf(','));

        return this.$ajax({
          url: this.server,
          method: 'post',
          data: {media: uploadData}
        })
      },

      /**
       * 删除图片
       * @param file
       * @param index
       */
      remove(file, index){
        let removeData;
        if(this.multiple){
          removeData = this.value.splice(index, 1)[0];
        }else{
          removeData = this.value;
          this.$emit('input', null);
        }

        if(this.valueType === 'data'){
          this.$ajax({
            url: this.serverRemove,
            pathData:{id: removeData._id},
          }).then(() => {
            this.$emit('remove', removeData);
          })
        }else{
          this.$emit('remove', removeData);
        }
      },
    },
    watch: {},
    created() {
    }
  }
</script>

<style lang="scss" scoped>
</style>
